//    Copyright (C) Kherty.  All rights reserved.
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using System.Reflection;
using System.Windows.Markup;
using OpenLS.Core.Notification;
using OpenLS.Core.Serialization;
using OpenLS.Drawing;

namespace OpenLS.Chart
{
    [ContentProperty("Charts")]
    public class PlotArea : ViewModelBase, IOfficeXmlSerializable,  IShape
    {
        private readonly ObservableCollection<Axis> _axes = new ObservableCollection<Axis>();
        private readonly ObservableCollection<ChartBase> _charts = new ObservableCollection<ChartBase>();
        private DataTable _dataTable;
        // private ExternalData _externalData;
        private Layout _layout = new Layout();
        // private PrintSettings _printSettings;
        private ShapeProperties _spPr;
        // private TextBody _txPr;

        public ObservableCollection<ChartBase> Charts
        {
            get { return _charts; }
        }

        public ObservableCollection<Axis> Axes
        {
            get { return _axes; }
        }


        public Layout Layout
        {
            get { return _layout; }
            set { _layout = value;notifyPropertyChanged("Layout"); }
        }

        public DataTable DataTable
        {
            get { return _dataTable; }
            set
            {
                _dataTable = value;
                notifyPropertyChanged("DataTable");
            }
        }

        public ExtensionList ExtensionList { get; set; }


        #region IOfficeXmlSerializable Members

        void IOfficeXmlSerializable.ReadXml(ReadContext context)
        {
            using (var c = context.Read("plotArea"))
            {
                _layout = c.ReadOptionalElement<Layout>("layout");
                var resolver = new AxisResolver();
                c.AddData(resolver);
                bool broken = false;
                while (!broken)
                {
                    switch (c.ReaderLocalName)
                    {
                        case "barChart":
                            Charts.Add(c.ReadElement<BarChart>());
                            break;
                        case "bar3DChart":
                            _charts.Add(c.ReadElement<Bar3DChart>());
                            break;
                        case "pie3DChart":
                            Charts.Add(c.ReadElement<Pie3DChart>());
                            break;
                        case "area3DChart":
                            Charts.Add(c.ReadElement<Area3DChart>());
                            break;
                        case "scatterChart":
                            _charts.Add(c.ReadElement<ScatterChart>());
                            break;
                        case "surface3DChart":
                            _charts.Add(c.ReadElement<Surface3DChart>());
                            break;
                        case "doughnutChart":
                            Charts.Add(c.ReadElement<DoughnutChart>());
                            break;
                        case "line3DChart":
                            Charts.Add(c.ReadElement<Line3DChart>());
                            break;
                        case "surfaceChart":
                            Charts.Add(c.ReadElement<SurfaceChart>());
                            break;
                        case "stockChart":
                            Charts.Add(c.ReadElement<StockChart>());
                            break;
                        case "ofPieChart":
                            Charts.Add(c.ReadElement<OfPieChart>());
                            break;
                        case "radarChart":
                            Charts.Add(c.ReadElement<RadarChart>());
                            break;
                        case "bubbleChart":
                            Charts.Add(c.ReadElement<BubbleChart>());
                            break;
                        case "lineChart":
                            Charts.Add(c.ReadElement<LineChart>());
                            break;
                        case "areaChart":
                            Charts.Add(c.ReadElement<AreaChart>());
                            break;
                        case "pieChart":
                            Charts.Add(c.ReadElement<PieChart>());
                            break;
                        default:
                            broken = true;
                            break;
                    }
                }
                bool hasAxis = true;
                while (hasAxis)
                {
                    Axis axis = null;
                    switch (c.ReaderLocalName)
                    {
                        case "catAx":
                            axis = new CategoryAxis();
                            break;
                        case "valAx":
                            axis = new ValueAxis();
                            break;
                        case "dateAx":
                            axis = new DateAxis();
                            break;
                        case "serAx":
                            axis = new SeriesAxis();
                            break;
                        default:
                            hasAxis = false;
                            break;
                    }
                    if (hasAxis)
                    {
                        IOfficeXmlSerializable aa = axis;
                        aa.ReadXml(c);
                        resolver.AddAxis(axis);
                        Axes.Add(axis);
                    }
                }
                resolver.Resolve();
                DataTable = c.ReadOptionalElement<DataTable>("dTable");
                ShapeProperties = c.ReadOptionalElement<ShapeProperties>("spPr");
                if (DataTable == null)
                    DataTable = c.ReadOptionalElement<DataTable>("dTable");
                ExtensionList = c.ReadOptionalElement<ExtensionList>("extLst");
            }
        }

        void IOfficeXmlSerializable.WriteXml(WriteContext context)
        {
            prepareAxes();
            using (WriteContext c = context.Write("plotArea"))
            {
                c.WriteOptionalElement(_layout);
                foreach (ChartBase s in Charts)
                    c.WriteElement(s);
                foreach (Axis a in Axes)
                    c.WriteElement(a);
                c.WriteOptionalElement(ShapeProperties);
                c.WriteOptionalElement(DataTable);
                c.WriteOptionalElement(ExtensionList);
            }
        }

        #endregion

        #region IShape Members

        public ShapeProperties ShapeProperties
        {
            get
            {
                if (_spPr == null)
                    _spPr = new ShapeProperties();
                return _spPr;
            }
            set
            {
                _spPr = value;
                notifyPropertyChanged("ShapeProperties");
            }
        }

        #endregion

        private void prepareAxes()
        {
            foreach (ChartBase chart in Charts)
            {
                foreach (Axis axis in chart.GetAxes())
                {
                    if (axis == null)
                        continue;
                    if (!Axes.Contains(axis))
                        Axes.Add(axis);
                }
            }
        }

    }
}